home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / pack / xpkrdcn.lha / xpkRDCN / decompr.asm < prev    next >
Assembly Source File  |  1992-12-12  |  4KB  |  141 lines

  1. ;---------------------------------------------------------------------------;
  2. ;                                        ;
  3. ; This is the Ross Data Compression implemented in 68000 assembler          ;
  4. ; by Niklas Sjöberg, 2:203/415.3@Fidonet                    ;
  5. ;                                        ;
  6. ;                                        ;
  7. ; The source is fully in the Public Domain. If you think you can improve    ;
  8. ; some parts, feel free to modify the code. HOWEVER, be carefull to comment ;
  9. ; the parts where you change!                            ;
  10. ;                                        ;
  11. ; On entry:                                    ;
  12. ; a0 points to XpkSubParams                            ;
  13. ;---------------------------------------------------------------------------;
  14. ; 921205 - Due to optimization comments may seem a bit weird.. Just try
  15. ;          to read 5-10 lines at the time I'm sure you'll get it right..
  16.     
  17.  
  18.     xdef _unpack            ; The only function called from
  19.                     ; the C-part of the library
  20.  
  21.     INCLUDE "libraries/xpksub.i"
  22.  
  23.     section    code
  24.  
  25. _unpack
  26.  
  27.     movem.l    a2-a6/d2-d7,-(SP)
  28.     move.l    xsp_InBuf(a0),a1    ; source pointer
  29.     move.l    xsp_InLen(a0),d1    ; source len
  30.     move.l    xsp_OutBuf(a0),a2    ; destination
  31.  
  32.     move.l    a1,a3            ; inbuff_idx  = inbuff
  33.     move.l    a2,a4            ; outbuff_idx = outbuff
  34.     move.l    a1,a5            ; inbuff_end  = inbuff
  35.     adda.l    d1,a5            ; + inbuff_len
  36.  
  37.     moveq    #0,d0
  38.     moveq    #0,d2
  39.     moveq    #0,d3
  40.     moveq    #0,d4
  41.     moveq    #0,d5
  42.     moveq    #0,d6
  43.     moveq    #0,d7
  44.     
  45. mloop    
  46.     subq.b    #1,d3
  47. ;    lsr.w    #1,d3            ; Check if we need to get a load of
  48.                     ; control bits
  49.     bpl.s    no_ctrlbits
  50.     move.w    (a3)+,d2        ; new load ctrl-bits
  51.                     ; 
  52.     moveq    #15,d3            ; ctrl_mask = 0x8000
  53. ; This is ugly. Since (in worst case) we may overrun the buffer by
  54. ; 15 bytes by not checking source and source-end. However, empty
  55. ; control-word means that we only copy 15 in worst case. Hell, we
  56. ; have 256 XPK_MARGIN bytes to play with :=) (I hope...)
  57.     cmp.l    a5,a3            ; main-loop. Go on until end of
  58.     bge.w    loopend            ; source buffer
  59.  
  60. no_ctrlbits
  61.                     ; First we have to check if data is
  62.                     ; compressed
  63. ;    move.w    d2,d7            ; If bits & mask turns out to be one
  64. ;    and.w    d3,d7            ; then data is compressed
  65.     btst    d3,d2
  66.     bne.s    crunched        ; char is crunched
  67.     move.b    (a3)+,(a4)+        ; otherwise, copy char and advance
  68.     bra.s    mloop            ; 
  69.  
  70. crunched
  71.     moveq    #0,d4            ; First find out what compressions method
  72.                     ; that was used.
  73.     move.b    (a3)+,d4        ; d4 will eventually contain 0-15
  74.     move.w    d4,d5            ; d5, contains count (further count may
  75.     and.b    #$f,d5            ; be needed for some methods.
  76.     lsr.b    #4,d4            ; The higher 4 bits of d4 is type, and
  77. ;    and.w    #$f,d4            ; the lower count
  78.  
  79.     cmpi.b    #2,d4            ; cmd > 2 then it's a short pattern
  80.     bls.s    no_spat            ; (3-15)
  81. ;    move.w    d5,d6            ; count is 3 chars higher actually
  82.     addq.b    #3,d5            ; d5 is never >15+3
  83.     moveq    #0,d7            ; to use d4 as loop-register
  84.     move.b    (a3)+,d7        ; decode offset
  85.     asl.w    #4,d7
  86.     add.w    d5,d7
  87.     move.l    a4,a6            ; Next copy d4 characters from a6
  88.     sub.l    d7,a6            ; to a4
  89.     subq.b    #1,d4
  90. s_loop    move.b    (a6)+,(a4)+        ;
  91.     dbf    d4,s_loop
  92.     bra.s     mloop            ; Jump to main loop
  93.  
  94.                     
  95. no_spat    tst.b    d4
  96.     ;cmpi.b    #0,d4            ;is it short rle?
  97.     bne.s    no_srle
  98.     addq.b    #2,d5            ; cnt += 3 (-1 for dbf loop)
  99.     move.b    (a3)+,d7        ; char to repeat d5 times
  100. sr_loop    move.b    d7,(a4)+        ; 
  101.     dbf    d5,sr_loop
  102.     bra.s    mloop            ; Main loop
  103.  
  104.  
  105. no_srle cmpi.b    #1,d4            ; is it a long rle?
  106.     bne.s    no_lrle
  107.     moveq    #0,d7
  108.     move.b    (a3)+,d7        ; if so, decode high/low count
  109.     asl.w    #4,d7            ; and add them since long RLE
  110.     add.w    d7,d5            ; is least 19 :
  111.     addi.w    #18,d5            ; cnt +=19 (-1 for dbf loop)
  112.     move.b    (a3)+,d7        ; char to set
  113. lr_loop    move.b    d7,(a4)+        ; 
  114.     dbf    d5,lr_loop
  115.     bra.s    mloop            ; Main loop
  116.  
  117.  
  118. no_lrle                    ; only one case left, long pattern
  119.     move.w    d5,d6            ; 
  120.     addq.w    #3,d6            ; at least 3 chars long pattern
  121.     moveq    #0,d7
  122.     move.b    (a3)+,d7        ; Decode and add high and low
  123.     asl.w    #4,d7            ; offset
  124.     add.w    d7,d6            ; 
  125.     moveq    #0,d5
  126.     move.b    (a3)+,d5        ; Next, get count
  127.     addi.w    #15,d5            ; which is at least 16 (-1 for loop)
  128.     move.l    a4,a6            ; source
  129.     sub.l    d6,a6            ; destination
  130. rl_loop    move.b    (a6)+,(a4)+
  131.     dbf    d5,rl_loop
  132.     bra.w    mloop
  133.  
  134. loopend
  135.     suba.l    a2,a4            ; This is the only exit point
  136.     move.l    a4,xsp_OutBufLen(a0)    ; return length to xpkmaster
  137.     movem.l    (SP)+,a2-a6/d2-d7
  138.     moveq    #0,d0
  139.     rts
  140.     END
  141.